package SSF.OS.UDP;

/*
 * udpSession.java
 *
 * Created: Sun Jun  6 21:04:03 1999 hongbol
 * Revised Fri Nov 5 1999 ato
 * @version 0.5
 */
import SSF.OS.*;
import SSF.OS.Socket.*;

/* The four UDP session variables: local_ip, remote_ip, local_port, remote_port
 *  identify an end2end UDP session
 *  if at least local_port, remote_ip, remote_port are valid.
 *  Else if only local_port (and possibly local_ip) are valid,
 *  while remote_ip = remote_port = -1, this is a local
 *  'listening server' ssession.
 */

/** A UDP session between two endpoints identified by their
 *  IP adresses and port numbers.
 */
public class udpSession extends ProtocolSession {

  /********************* Attribute Variables *********************/

  /** source (local) IP address */
  public int local_ip;

  /** source (local) port number */
  public int local_port;

  /** destination (remote) IP address */
  public int remote_ip;

  /** destination (remote) port number */
  public int remote_port;

  /*  udpSessionMaster for this session */
  udpSessionMaster udpMst;

  /*  udp socket for this session */
  udpSocket udpsocket;

  /* empty dataMessage for passing incoming messages to socket,
   * can be safely reused */
  dataMessage emptyMsg;

  int  max_datagram_size;

  /************************* Constructors ************************/

  public udpSession(udpSessionMaster udpms, udpSocket sock) {
    udpMst = udpms;
    udpsocket = sock;
    local_port = sock.local_port;
    local_ip = sock.local_ip;
    remote_port = sock.remote_port;
    remote_ip = sock.remote_ip;
    max_datagram_size = udpms.max_datagram_size;
    emptyMsg = new dataMessage(null, 0);
  }

  /************************ Class Methods ***********************/

  public boolean push(ProtocolMessage message, ProtocolSession fromSession) 
    throws ProtocolException {

    if (fromSession instanceof IP) {
      UDP_Header udpHdr = (UDP_Header)message;

      // if this is a 'listening' server session, we store
      // the header information in the socket so that the server can
      // know who contacted it.
      if(remote_ip == -1) {
        udpsocket.last_remote_ip = ((IpHeader)udpHdr.previous()).SOURCE_IP;
        udpsocket.last_remote_port = udpHdr.SOURCE_port;
        udpsocket.last_local_ip = ((IpHeader)udpHdr.previous()).DEST_IP;
      }

      if(udpHdr.payload() != null) {
        udpsocket.messageBuffer((dataMessage)udpHdr.payload());
        udpHdr.dropPayload();   // may recycle now if desired
      } else {
        emptyMsg.size = udpHdr.length;
        udpsocket.messageBuffer(emptyMsg);
      }
      return true;
    } else {
      UDP_Header udp_msg;
      IpHeader ip_msg;
      dataMessage dmsg = (dataMessage)message;

      udp_msg = new UDP_Header(local_port, remote_port, dmsg.size);
      ip_msg = new IpHeader(Protocols.UDP_PRTL_NUM, local_ip, remote_ip);

      if(dmsg.data != null)
        udp_msg.carryPayload(dmsg);
      ip_msg.carryPayload(udp_msg);
    
      try {
        return (udpMst.ipsess.push(ip_msg, this));
      } catch (ProtocolException e) {
        System.err.println(e);
      }
    }
    return false;
  }
} // udpSession
